package container

import "math"

type Array[T any] struct {
	internal     []T
	minBlockSize int
	defaultValue T
}

func NewUnsortedArray[T any]() *Array[T] {
	return &Array[T]{
		internal:     nil,
		minBlockSize: 8,
		defaultValue: *new(T),
	}
}

func (r *Array[T]) Get(index int) (T, bool) {
	if index >= len(r.internal) {
		return r.defaultValue, false
	}
	return r.internal[index], true
}

func (r *Array[T]) Add(data T) {
	//检查剩余空间
	left := cap(r.internal) - len(r.internal)
	if left <= 0 {
		r.grow()
	}
	//写入
	r.internal = append(r.internal, data)
}

func (r *Array[T]) Remove(index int) {
	curLen := len(r.internal)
	if index >= curLen {
		//超出了，不用管
		return
	}
	//index位置与最后的元素互换
	r.internal[index] = r.internal[curLen-1]
	r.internal = r.internal[0 : curLen-1]
}

func (r *Array[T]) grow() {
	cap := cap(r.internal)
	len := len(r.internal)
	growSize := int(math.Max(float64(cap>>1), float64(r.minBlockSize)))
	newArr := make([]T, growSize+cap)
	copy(newArr, r.internal)
	r.internal = newArr[0:len]
}

func (r *Array[T]) Iterate(f func(data T)) {
	internal := r.internal
	for index := range internal {
		f(internal[index])
	}
}

func (r *Array[T]) Count() int {
	return len(r.internal)
}
